/*
 * @Author       : NaN 353362604@qq.com
 * @Date         : 2023-02-13 13:33:14
 * @LastEditTime: 2023-02-15 14:41:34
 * @LastEditors: 飞越疯人院 353362604@qq.com
 * @FilePath     : \AdminStration\src\Pages\Front\Assets\Command\Command.jsx
 * @Description  :
 */
import { useState, useEffect, useCallback } from 'react'
import { useRequest } from 'ahooks'
import { message, Tree } from 'antd'
import { CaretDownOutlined } from '@ant-design/icons'
import { useLatest } from '@ant-design/pro-components'
import { Http } from '../../../../Common/Api'
import { FrontModalBox } from '../Modal'

import { TreeToLevel } from '../../../../Common/Modal/config'

import { WebTemplateUrl } from '../Template/configuration'

const CallIconList = {
    1: { title: '安全帽', icon: 'command01.png' },
    2: { title: '执法记录仪', icon: 'command02.png' },
}

const BroadcastIconList = {
    1: { title: '语音广播', icon: 'command01.png' },
    2: { title: '视频对讲', icon: 'command02.png' },
    3: { title: '语音对讲', icon: 'command02.png' },
}

const KING_ADMIN = {
    Account: '18945080905',
    Password: '18945080905',
    LogLevel: 'debug',
    ServerAddr: 'norsos.lionking110.com',
}

export const CommandBox = ({
    data,
    type,
    className,
    OptionsEvent,
    OptionsClickEvent,
    RightBox,
    MapAddress,
    CMT_ADMIN,
    sceneId,
}) => {
    // 传入的列表数据
    const [treeData, setTreeData] = useState([])
    // 获取监控列表
    const { runAsync: getCameraListByOrg } = useRequest(Http, { manual: true })

    // 初始化三方sdk
    const [CMTSDK, setCMTSDK] = useState()
    const [KINSKD, setKINSKD] = useState()
    const SDKLatest = useLatest(CMTSDK)

    const [expandedKeys, setExpandedKeys] = useState([])
    const [checkedKeys, setCheckedKeys] = useState([])

    const checkedKeysLatest = useLatest(checkedKeys)

    const onSelect = (key, { node }) => {
        if (node.level === 1) setExpandedKeys(key)
        if (node.level === 2) {
            let data = expandedKeys
            const number = data.findIndex(v => v === node.key)
            if (key.length !== 0 && node.children.length === 0) {
                getCameraListByOrg({ url: 'getCameraListByOrg', data: { OrganizationUuid: key[0] } }).then(res => {
                    const list = JSON.parse(
                        JSON.stringify(res.list)
                            .replace(/cameraName/g, 'title')
                            .replace(/uuid/g, 'key'),
                    )
                    setTreeData(e => updateTreeData(e, key[0], list))
                    setExpandedKeys([...data, ...key])
                })
            } else {
                if (number !== -1) {
                    data.splice(number, 1)
                    setExpandedKeys([...data])
                } else setExpandedKeys([...data, ...key])
            }
        }
    }

    const updateTreeData = (list, key, children) =>
        list.map(node => {
            if (node.key === key) return { ...node, children }
            if (node.children) return { ...node, children: updateTreeData(node.children, key, children) }
            return node
        })

    const onCheck = key => {
        if (key.length !== 0) OptionsEvent.emit({ type, key })
        else OptionsEvent.emit(undefined)
        checkedKeysLatest.current = key
        setCheckedKeys(checkedKeysLatest.current)
    }

    useEffect(() => {
        if (data) {
            setTreeData(data)
            switch (type) {
                case 1:
                    InItCmtClientService()
                    break
                case 2:
                    InItLionKing()
                    break
                default:
                    break
            }
            return () => {
                switch (type) {
                    case 1:
                        UnInItCmtClientService()
                        break
                    case 2:
                        UnInItLionKing()
                        break
                    default:
                        break
                }
            }
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [type, data])
    const [UserList, setUserList] = useState([])
    // 安全帽socket事件
    useEffect(() => {
        if (CMTSDK && type === 1) {
            window.onEventFiredEvent = e => {
                const { event, code } = e
                switch (event) {
                    case 'onOpen':
                        window.onopen()
                        break
                    case 'onEventRegistered':
                        if (Number(code) === 200) {
                            message.success('指挥中心登录成功!')
                            window.setConfig()
                        } else {
                            message.error('指挥中心登录失败!')
                        }
                        break
                    case 'onClose':
                        CMTSDK.WSClose()
                        CMTSDK.init()
                        message.error('指挥中心重新连接中...')
                        break
                    case 'onEventUserStatusUpdate':
                        if (data[0].children.find(v => v.key === e.sipNum))
                            MapAddress.emit({ data: data[0].children.find(v => v.key === e.sipNum), event: e })
                        setUserList(user => {
                            const LNum = user.findIndex(v => v.sipNum === e.sipNum)
                            if (LNum === -1) {
                                return [...user, e]
                            } else {
                                user[LNum].status = e.status
                                return [...user]
                            }
                        })
                        break
                    case 'onEventConnected':
                        e.type === 'audio' && console.log('语音事件', e)
                        e.type === 'video' && console.log('视频事件', e)
                        break
                    default:
                        // console.log('通知事件', e)
                        break
                }
            }
            window.onCmdResultEvent = e => {
                const { cmdName } = e
                switch (cmdName) {
                    case 'registerSip':
                        message.loading('指挥中心初始化中')
                        break
                    default:
                        // console.log('返回事件', e)
                        break
                }
            }
        }

        return () => {
            if (type === 1) {
                window.onEventFiredEvent = () => {}
                window.onCmdResultEvent = () => {}
            }
        }
    }, [MapAddress, CMTSDK, data, type])

    // 初始化安全帽
    const InItCmtClientService = () => {
        const { user, password, host, serverPort } = CMT_ADMIN
        SDKLatest.current = new window.CmtWsClientHelper()
        window.onopen = () => SDKLatest.current.registerSip(user, password, host, serverPort)
        window.setConfig = () =>
            SDKLatest.current.setServiceConfig(
                'videoPlayUrl',
                `http://${host}:1080/vdis/videoPlayer?user=${user}&passwd=${password}`,
            )
        window.location = 'CmtClientService://'
        SDKLatest.current.addCmtEventHandler(new window.CallbackHandler())
        SDKLatest.current.init()
        setCMTSDK(SDKLatest.current)
    }

    // 卸载安全帽
    const UnInItCmtClientService = () => {
        SDKLatest.current.closeService()
        SDKLatest.current.WSClose()
        window.onopen = () => null
        window.setConfig = () => null
    }
    // 初始化IP广播
    const InItLionKing = () => {
        // console.log('初始化IP广播')
        let sdk = null
        message.loading('IP广播初始化中...')
        sdk = new window.SOS.SDK(KING_ADMIN)
        sdk.addEventListener(window.SOS.EVENT.SDK_STATE, (event, code, description) => {
            switch (event) {
                case window.SOS.EVENT.SDK_STATE_CODE.WARN:
                    // 一般是网络原因与服务器连接断开，会warn
                    message.info('网络波动导致连接中断,请重试!')
                    break
                case window.SOS.EVENT.SDK_STATE_CODE.ERROR:
                    if (code === window.SOS.ERROR_CODE.LOGIN_CONFLICT) {
                        // message.info('帐号已经在其他设备登录!')
                        sdk && sdk.destroy()
                        sdk = null
                    }
                    break
                case window.SOS.EVENT.SDK_STATE_CODE.SUCCESS:
                    if (sdk.isTest()) message.info('测试环境调试')
                    break
                default:
                    break
            }
        })

        sdk.init()
            .then(() => {
                setKINSKD(() => {
                    // 初始化成功（这里成功之后，也会通过sdk.addEventListener(SOS.EVENT.SUCCESS)的消息通知到）
                    message.success('IP广播初始化成功!')
                    btnDeviceList(sdk)
                    return sdk
                })
            })
            .catch(() => message.error('IP广播初始化失败!'))
    }
    const [LionKingList, setLionKingList] = useState([])
    // 在线设备列表
    const btnDeviceList = async sdk => {
        if (sdk) {
            try {
                let rsp = await sdk.deviceList({
                    PageSize: 10,
                    PageNum: 1,
                    Filters: [
                        [{ Key: 'AppState', Type: 'str', Op: '=', Value: 'online' }],
                        [{ Key: 'DeviceType', Type: 'str', Op: '=', Value: 'alarm' }],
                    ],
                    OrderKey: 'OnlineTime',
                    Desc: true,
                })
                setLionKingList(rsp.RecordList || [])
            } catch (error) {
                message.error('获取IP广播设备在线状态失败!')
            }
        } else {
            alert('获取设备列表失败，请先启动SDK')
        }
    }

    // 卸载IP广播
    const UnInItLionKing = () => {
        if (KINSKD) {
            KINSKD.destroy()
                .then(() => {
                    // eslint-disable-next-line no-const-assign
                    KINSKD = null
                })
                .catch(() => {
                    // eslint-disable-next-line no-const-assign
                    KINSKD = null
                })
        }
    }
    const [TaskCode, setTaskCode] = useState()
    // 开始麦克风广播
    const btnDeviceMicrophoneMutilBoradcastStart = async () => {
        if (KINSKD) {
            try {
                message.loading('正在组件广播...')
                const number = checkedKeysLatest.current.findIndex(v => v === 'LiveVideoTreeTitleUuid')
                if (number !== -1) checkedKeysLatest.current.splice(number, 1)
                let rsp = await KINSKD.microphoneMutilBoradcastStart({
                    DeviceIds: checkedKeysLatest.current.map(item => Number(item)),
                })
                setTaskCode(rsp.TaskCode)
                message.success('组建成功，你可以使用麦克风广播了')
            } catch (error) {
                message.error('组建终端失败')
            }
        } else {
            alert('麦克风广播失败，请先启动SDK')
        }
    }

    const btnDeviceMicrophoneMutilBoradcastStop = async () => {
        if (KINSKD) {
            try {
                message.loading('正在停止广播...')
                await KINSKD.microphoneMutilBoradcastStop({ TaskCode: TaskCode })
                message.success('广播停止')
            } catch (error) {
                message.error('麦克风停止失败')
            }
        } else {
            alert('广播停止失败，请先启动SDK')
        }
    }

    const btnPermissionAudio = async () => {
        window.SOS.PERMISSION.getAudio()
            .then(() => alert('获取麦克风权限成功'))
            .catch(error => alert('获取麦克风权限失败\n\n' + error))
    }

    const [VideoCode, setVideoCode] = useState()
    const [RecordList, setRecordList] = useState()

    const stopCallback = async () => {
        try {
            const rsp = await KINSKD.videoMonitorStop({ TaskCode: VideoCode })
            console.log('停止监控视频成功', rsp)
        } catch (error) {
            console.log('停止监控视频失败', error)
        }
    }

    const videoMonitorStart = async () => {
        stopCallback()
        try {
            const task = await KINSKD.videoMonitorStart({
                DeviceId: Number(checkedKeysLatest.current[0]),
                VideoDomId: 'html_video_remote',
                OnStop: stopCallback,
            })
            setVideoCode(task.TaskCode)
            console.log('获取监控视频成功 taskCode:', task.TaskCode)
            console.log('视频列表', checkedKeysLatest.current[0])
        } catch (error) {
            console.log('获取监控视频失败', error)
        }
    }

    const deviceAlarmRecordList = useCallback(async () => {
        try {
            const rsp = await KINSKD.deviceAlarmRecordList({
                PageSize: 10000,
                PageNum: 1,
                Filters: [],
                OrderKey: 'StartTime',
                Desc: true,
            })

            const list = rsp.RecordList.find(v => v.State === 'report')
            setRecordList(list)

            // rsp.RecordList这个数组结构中就存放着alarmTaskObject，你可以取出State是report状态的任务进行接警
        } catch (error) {
            console.log('获取设备告警列表失败', error)
        }
    }, [KINSKD])

    // 监听点击事件
    OptionsClickEvent.useSubscription(val => {
        const { state, click } = val
        if (state === type) {
            switch (click) {
                case 'MonitorVideo':
                    OpenMonitorVideo(checkedKeys)
                    break
                case 'makeAudioCall':
                    const AudioCall = JSON.parse(JSON.stringify(checkedKeys)).filter(
                        v => v !== 'CommandCentreTreeTitleUuid',
                    )
                    AudioCall.forEach(item => CMTSDK.makeAudioCall(item, 0))
                    break
                case 'makeVideoCall':
                    const VideoCall = JSON.parse(JSON.stringify(checkedKeys)).filter(
                        v => v !== 'CommandCentreTreeTitleUuid',
                    )
                    VideoCall.forEach(item => CMTSDK.makeVideoCall(item, 0, 0))
                    break
                case 'getMicrophone':
                    btnPermissionAudio()
                    break
                case 'radioBroadcast':
                    btnDeviceMicrophoneMutilBoradcastStart()
                    break
                case 'offRadioBroadcast':
                    btnDeviceMicrophoneMutilBoradcastStop()
                    break
                case 'videoBroadcast':
                    videoMonitorStart()
                    console.log('视频监控')
                    break
                default:
                    break
            }
        }
    })

    const OpenMonitorVideo = data => {
        const TreeData = TreeToLevel(treeData)
        const videoList = data.map(item => TreeData.find(v => v.key === item))
        RightBox.emit({ type, list: videoList })
    }

    const [OptionsCall, setOptionsCall] = useState()

    return (
        <>
            <div id="html_audio_remote"></div>
            <video id="html_video_remote"></video>

            <div className="RecordList">
                <div>求救列表</div>
                {/* {RecordList} */}
            </div>

            <Tree
                rootClassName={`TreeClass ${className}`}
                switcherIcon={<></>}
                checkable
                expandedKeys={expandedKeys}
                checkedKeys={checkedKeys}
                onSelect={onSelect}
                onCheck={onCheck}
                treeData={treeData}
                titleRender={e => {
                    return (
                        <>
                            {e.children && e.children !== 0 ? (
                                <div className="TreeTitle">
                                    <div> {e.title}</div>
                                    <div />
                                    <CaretDownOutlined
                                        style={{
                                            transform: `${
                                                expandedKeys.findIndex(v => v === e.key) !== -1
                                                    ? 'rotate(0)'
                                                    : 'rotate(90deg)'
                                            }`,
                                        }}
                                    />
                                </div>
                            ) : (
                                <div className="TreeItem">
                                    <div className="content">
                                        {(() => {
                                            switch (type) {
                                                case 1:
                                                    return (
                                                        <>
                                                            <div>
                                                                {CallIconList[e.helmetType].title} {e.title}
                                                            </div>
                                                            <img
                                                                src={WebTemplateUrl + CallIconList[e.helmetType].icon}
                                                                alt=""
                                                            />
                                                            {UserList.find(v => v.sipNum === e.key)?.status === '1' ? (
                                                                <div className="onLine">在线</div>
                                                            ) : UserList.find(v => v.sipNum === e.key)?.status ===
                                                              '2' ? (
                                                                <div className="offLine">离线</div>
                                                            ) : (
                                                                <div className="Loading">通话中...</div>
                                                            )}
                                                        </>
                                                    )
                                                case 2:
                                                    return (
                                                        <>
                                                            <div>
                                                                {BroadcastIconList[e.broadcastType].title} {e.title}
                                                            </div>
                                                            <img
                                                                src={
                                                                    WebTemplateUrl +
                                                                    BroadcastIconList[e.broadcastType].icon
                                                                }
                                                                alt=""
                                                            />
                                                            {LionKingList.findIndex(v => v.Id === Number(e.key)) !==
                                                            -1 ? (
                                                                <div className="onLine">在线</div>
                                                            ) : (
                                                                <div className="offLine">离线</div>
                                                            )}
                                                        </>
                                                    )
                                                case 3:
                                                    return (
                                                        <>
                                                            <div> {e.title}</div>
                                                            <img src={WebTemplateUrl + 'command04.png'} alt="" />
                                                        </>
                                                    )
                                                default:
                                                    ;<div> 未知的设备类型 </div>
                                                    break
                                            }
                                        })()}
                                    </div>
                                    {type === 1 && (
                                        <div
                                            className="trajectory"
                                            onClick={() => {
                                                setOptionsCall({
                                                    type: 'CommandTrajectory',
                                                    data: {
                                                        title: e.title + '历史轨迹',
                                                        data: { ren: e, sceneId: sceneId },
                                                    },
                                                })
                                            }}
                                        >
                                            历史轨迹
                                        </div>
                                    )}
                                </div>
                            )}
                        </>
                    )
                }}
            />
            <FrontModalBox OptionsCall={OptionsCall} />
        </>
    )
}
